﻿// -----------------------------------------------------------------------
// <copyright file="IMG_OpenSave.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace ImageProcessing.IMG_Processor
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public static class IMG_OpenSave
    {
        /// <summary>
        /// string containing the int values of p3 file
        /// </summary>
        private static string[] imgStringArr;

        /// <summary>
        /// integer used as a counter in the p3 helper function to acces the array
        /// </summary>
        private static int imgxCnt = 0;

        /// <summary>
        /// Opens image of any format
        /// </summary>
        /// <param name="path">takes image path</param>
        /// <returns>return buffer</returns>
        public static Entities.IMG_Image IMG_Open(string path)
        {
            try
            {
                System.IO.FileInfo img_FileInfo = new System.IO.FileInfo(path);
                if (img_FileInfo.Extension == ".ppm" | img_FileInfo.Extension == ".PPM")
                {
                    FileStream img_Fs = new FileStream(path, FileMode.Open);
                    StreamReader img_Sr = new StreamReader(img_Fs);
                    string img_TmpStr = img_Sr.ReadLine();
                    if (img_TmpStr == "P3" | img_TmpStr == "p3")
                    {
                        Entities.IMG_Image image = IMG_OpenP3(img_Sr);
                        img_Sr.Close();
                        img_Fs.Close();
                        return image;
                    }
                    else if (img_TmpStr == "P6" | img_TmpStr == "p6")
                    {
                        Entities.IMG_Image image = IMG_OpenP6(img_Sr, img_Fs);
                        img_Sr.Close();
                        img_Fs.Close();
                        return image;
                    }
                    else
                    {
                        img_Sr.Close();
                        img_Fs.Close();
                        return null;
                    }
                }
                else
                {
                    return IMG_OpenCommonFormat(path);
                }
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// Saves Image in any format
        /// </summary>
        /// <param name="img_buffer">buffer array</param>
        /// <param name="path">string of path</param>
        /// <param name="img_ExIndex">indec of selection</param>
        public static void IMG_Save(Entities.IMG_Image img_buffer, string path, int img_ExIndex)
        {
            try
            {
                if (img_ExIndex == 1)
                {
                    IMG_SaveP3(img_buffer, path);
                }
                else if (img_ExIndex == 2)
                {
                    IMG_SaveP6(img_buffer, path);
                }
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// function to convert buffer to bitmap
        /// </summary>
        /// <param name="img_buffer">the buffer</param>
        /// <returns>bitmap object</returns>
        public static Bitmap IMG_BufferToBItmap(Entities.IMG_Image img_buffer)
        {
            try
            {
                return img_buffer.BitmapOfImage();
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// open common formats (jpg,bmp ....) image function
        /// </summary>
        /// <param name="path">path of required image</param>
        /// <returns>bitmap object that has the opened image</returns>
        private static Entities.IMG_Image IMG_OpenCommonFormat(string path)
        {
            try
            {
                Bitmap img_bitmapImage = new Bitmap(path);
                Entities.IMG_Image img = new Entities.IMG_Image(img_bitmapImage);
                return img;
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// open p3 image fn
        /// </summary>
        /// <param name="img_Sr">The img_ sr.</param>
        /// <returns>
        /// bitmap object that has the p3 opened image
        /// </returns>
        private static Entities.IMG_Image IMG_OpenP3(StreamReader img_Sr)
        {
            try
            {
                int img_width, img_height;

                string img_TmpStr = img_Sr.ReadLine();

                if (img_TmpStr[0] == '#')
                {
                    img_TmpStr = img_Sr.ReadLine();
                    imgStringArr = img_TmpStr.Split(' ');
                    img_width = int.Parse(imgStringArr[0]);
                    img_height = int.Parse(imgStringArr[1]);
                }
                else
                {
                    imgStringArr = img_TmpStr.Split(' ');
                    img_width = int.Parse(imgStringArr[0]);
                    img_height = int.Parse(imgStringArr[1]);
                }

                img_TmpStr = img_Sr.ReadLine();
                img_TmpStr = img_Sr.ReadToEnd();
                imgStringArr = img_TmpStr.Split(' ', '\r', '\n');

                Entities.IMG_Image img_buffer = new Entities.IMG_Image(img_width, img_height);

                Entities.Pixel img_PixelColor;

                for (int i = 0; i < img_height * img_width; i++)
                {
                    int red = GetNextValue();
                    int green = GetNextValue();
                    int blue = GetNextValue();
                    img_PixelColor = new Entities.Pixel(red, green, blue);
                    img_buffer.ImagePixels[i] = img_PixelColor;
                }

                imgxCnt = 0;
                return img_buffer;
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// IMs the g_ open p6.
        /// </summary>
        /// <param name="img_Sr">The img_ sr.</param>
        /// <param name="img_Fs">The img_ fs.</param>
        /// <returns>opened image</returns>
        private static Entities.IMG_Image IMG_OpenP6(StreamReader img_Sr, FileStream img_Fs)
        {
            try
            {
                int img_Offset = 0;
                int img_width, img_height;

                img_Offset += 2;
                img_Offset++;
                string img_tmpStr = img_Sr.ReadLine();
                if (img_tmpStr[0] == '#')
                {
                    img_Offset += img_tmpStr.Length;
                    img_Offset++;
                    img_tmpStr = img_Sr.ReadLine();
                    img_Offset += img_tmpStr.Length;
                    img_Offset++;
                    imgStringArr = img_tmpStr.Split(' ');
                    img_width = int.Parse(imgStringArr[0]);
                    img_height = int.Parse(imgStringArr[1]);
                }
                else
                {
                    img_Offset += img_tmpStr.Length;
                    img_Offset++;
                    imgStringArr = img_tmpStr.Split(' ');
                    img_width = int.Parse(imgStringArr[0]);
                    img_height = int.Parse(imgStringArr[1]);
                }

                img_tmpStr = img_Sr.ReadLine();
                img_Offset += img_tmpStr.Length;
                img_Offset++;
                byte[] img_byteArr = new byte[img_height * img_width * 3];
                img_Fs.Seek(img_Offset, 0);
                img_Fs.Read(img_byteArr, 0, img_height * img_width * 3);
                Entities.IMG_Image img_buffer = new Entities.IMG_Image(img_width, img_height);
                Entities.Pixel img_Color;
                int byte_buffer_cnt = 0;
                int img_Red, img_Green, img_Blue;
                for (int i = 0; i < img_height * img_width; i++)
                {
                    img_Red = img_byteArr[byte_buffer_cnt++];
                    img_Green = img_byteArr[byte_buffer_cnt++];
                    img_Blue = img_byteArr[byte_buffer_cnt++];
                    img_Color = new Entities.Pixel(img_Red, img_Green, img_Blue);
                    img_buffer.ImagePixels[i] = img_Color;
                }

                return img_buffer;
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// save a P3 image 
        /// </summary>
        /// <param name="img_buffer">a buffer containing the image components</param>
        /// <param name="path">the path to save the image</param>
        private static void IMG_SaveP3(Entities.IMG_Image img_buffer, string path)
        {
            try
            {
                string img_Tmp_str;
                int img_height, img_width;
                FileStream img_Fs = new FileStream(path, FileMode.Create);
                StreamWriter img_Sr = new StreamWriter(img_Fs);
                img_Tmp_str = "P3\n";
                img_Sr.Write(img_Tmp_str);
                img_Tmp_str = "#comment\n";
                img_Sr.Write(img_Tmp_str);
                img_Tmp_str = img_buffer.Width.ToString() + " " + img_buffer.Height.ToString() + "\n";
                img_Sr.Write(img_Tmp_str);
                img_Tmp_str = "255\n";
                img_Sr.Write(img_Tmp_str);
                img_Tmp_str = string.Empty;
                img_width = img_buffer.Width;
                img_height = img_buffer.Height;
                for (int i = 0; i < img_height * img_width; i++)
                {
                    img_Tmp_str += img_buffer.ImagePixels[i].Red + " " + img_buffer.ImagePixels[i].Green + " " + img_buffer.ImagePixels[i].Blue + " ";
                }

                img_Sr.WriteLine(img_Tmp_str);
                img_Sr.Close();
                img_Fs.Close();
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// saves the file as p6 format
        /// </summary>
        /// <param name="img_buffer">the image buffer</param>
        /// <param name="path">the path to save in</param>
        private static void IMG_SaveP6(Entities.IMG_Image img_buffer, string path)
        {
            try
            {
                int img_height, img_width;

                FileStream img_Fs = new FileStream(path, FileMode.Create);
                string img_tmp_str = "P6\n\r#comment\n\r";
                img_tmp_str += img_buffer.Width.ToString() + " " + img_buffer.Height.ToString() + "\n\r";
                img_tmp_str += "255\n\r";
                byte[] img_TempByteArr = System.Text.Encoding.ASCII.GetBytes(img_tmp_str);
                img_Fs.Write(img_TempByteArr, 0, img_TempByteArr.Length);
                img_width = img_buffer.Width;
                img_height = img_buffer.Height;
                byte[] img_ByteArr = new byte[img_width * img_height * 3];
                int img_byte_BufferCnt = 0;
                for (int i = 0; i < img_height * img_width; i++)
                {
                    img_ByteArr[img_byte_BufferCnt++] = (byte)img_buffer.ImagePixels[i].Red;
                    img_ByteArr[img_byte_BufferCnt++] = (byte)img_buffer.ImagePixels[i].Green;
                    img_ByteArr[img_byte_BufferCnt++] = (byte)img_buffer.ImagePixels[i].Blue;
                }

                img_Fs.Write(img_ByteArr, 0, img_ByteArr.Length);
                img_Fs.Close();
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// helper function used by open P3 function
        /// </summary>
        /// <returns>the next int value in the string </returns>
        private static int GetNextValue()
        {
            try
            {
                while (true)
                {
                    if (imgStringArr[imgxCnt] != string.Empty)
                    {
                        return int.Parse(imgStringArr[imgxCnt++]);
                    }
                    else
                    {
                        imgxCnt++;
                    }
                }
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }

        /// <summary>
        /// change any bitmap image to the corresponding buffer 
        /// </summary>
        /// <param name="img_bufferImage">bitmap image</param>
        /// <returns>the buffer corresponding to the bitmap image</returns>
        private static Entities.IMG_Image ChangebitmapToBuffer(Bitmap img_bufferImage)
        {
            try
            {
                Entities.IMG_Image img = new Entities.IMG_Image(img_bufferImage);
                return img;
            }
            catch (Exception img_Ex)
            {
                Logger.LogException(img_Ex);
                throw;
            }
        }
    }
}
